home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / proc / procRpc.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  45KB  |  1,351 lines

  1. /*
  2.  * procRpc.c --
  3.  *
  4.  *    Procedures to handle remote procedure calls on behalf of migrated
  5.  *    processes, and for initial setup of migrated processes.
  6.  *
  7.  * Copyright (C) 1986, 1988 Regents of the University of California
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/proc/procRpc.c,v 9.22 92/06/15 22:29:39 jhh Exp $ SPRITE (Berkeley)";
  19. #endif /* not lint */
  20.  
  21. #include <sprite.h>
  22. #include <stdlib.h>
  23. #include <proc.h>
  24. #include <procInt.h>
  25. #include <procMigrate.h>
  26. #include <mach.h>
  27. #include <fs.h>
  28. #include <migrate.h>
  29. #include <byte.h>
  30. #include <sig.h>
  31. #include <vm.h>
  32. #include <sys.h>
  33. #include <rpc.h>
  34. #include <timer.h>
  35. #include <sched.h>
  36. #include <sync.h>
  37. #include <sysSysCall.h>
  38. #include <sysSysCallParam.h>
  39. #include <devVid.h>
  40. #include <prof.h>
  41. #include <string.h>
  42. #include <stdio.h>
  43. #include <bstring.h>
  44.  
  45. /* 
  46.  * Macro to verify that a process is migrated.  If its state is MIGRATED, 
  47.  * it's okay.  Otherwise, both the MIGRATING and MIGRATION_DONE flags must 
  48.  * be on.  The MIGRATING flag must be on because the home process hasn't 
  49.  * finished migrating yet (hasn't context switched).  The MIGRATION_DONE 
  50.  * flag must be on because otherwise we shouldn't yet be getting RPC 
  51.  * requests from the peer process.
  52.  */
  53. #define IsMigrated(procPtr) \
  54.     ((procPtr)->state == PROC_MIGRATED \
  55.      || (((procPtr)->genFlags & (PROC_MIGRATING|PROC_MIGRATION_DONE)) \
  56.      == (PROC_MIGRATING|PROC_MIGRATION_DONE)))
  57.     
  58. /* 
  59.  * The PARANOIA code contains temporary checks to verify that 
  60.  * Proc_StringNCopy is being used correctly. -mdk 27-May-91.
  61.  */
  62. #define PARANOIA    1
  63. #if PARANOIA
  64. #define IsUserAddr(x)    ((x) >= mach_FirstUserAddr && (x) <= mach_LastUserAddr)
  65. Boolean procStringChecks = FALSE; /* do some paranoia checks on StringNCopy */
  66. #endif
  67.  
  68. static ReturnStatus     RpcProcExit _ARGS_((Proc_ControlBlock *procPtr, 
  69.                 Address dataPtr, int dataLength, 
  70.                 Address *replyDataPtr, 
  71.                 int *replyDataLengthPtr));
  72. static ReturnStatus     RpcProcFork _ARGS_((Proc_ControlBlock *parentProcPtr, 
  73.                 Address dataPtr, int dataLength, 
  74.                 Address *replyDataPtr, 
  75.                 int *replyDataLengthPtr));
  76. static ReturnStatus     RpcProcExec _ARGS_((Proc_ControlBlock *procPtr, 
  77.                 Address dataPtr, int dataLength, 
  78.                 Address *replyDataPtr, 
  79.                 int *replyDataLengthPtr));
  80. static ReturnStatus     RpcRemoteCall _ARGS_((Proc_RemoteCall *callPtr, 
  81.                 Address dataPtr, int dataLength, 
  82.                 Address *replyDataPtr,
  83.                 int *replyDataLengthPtr));
  84. static ReturnStatus    WaitSanityChecks _ARGS_((Proc_ControlBlock *procPtr,
  85.                 int clientID));
  86.  
  87. typedef ReturnStatus ((*PRS) ());
  88.  
  89. /*
  90.  * When a migrated system call is handled, a local procedure is called
  91.  * to perform the system call.  If the procedure has side effects,
  92.  * then before the results are returned, the process state on the
  93.  * remote node needs to be updated.  (This will be the case for
  94.  * routines such as Proc_SetIDs or Fs_Open.)  The "CallBack" type
  95.  * defines a structure containing pointers to two procedures.
  96.  *
  97.  * For each system call, there are several possibilities for procedures to
  98.  * be invoked:
  99.  *
  100.  *    1) The call should never be migrated (or has not been implemented).
  101.  *       This is a fatal error and is identified by localPtr being "RSNIL".
  102.  *    2) The call is a typical call that transfers data but has no side
  103.  *       effects.  localPtr is set, but sideEffectsPtr is RSNIL.
  104.  *    3) The call has side effects.  localPtr and sideEffectsPtr are non-NIL.
  105.  */
  106.  
  107. typedef struct {
  108.     PRS localPtr;        /* procedure to process call locally */
  109.     PRS sideEffectsPtr;        /* procedure to update info on remote node */
  110. } CallBack;
  111.  
  112. #define RSNIL ((PRS) NIL)
  113.  
  114. static CallBack callBackVector[] = {
  115. /*
  116.  *     callPtr      (why)        sideEffectsPtr    call number
  117.  */
  118.     { RpcProcFork,            RSNIL }, /* SYS_PROC_FORK       0 */
  119.     { RpcProcExec,            RSNIL }, /* SYS_PROC_EXEC       1 */
  120.     { RpcProcExit,            RSNIL }, /* SYS_PROC_EXIT       2 */
  121.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_SYNC_WAITTIME       3 */
  122.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_TEST_PRINTOUT       4 */
  123.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_TEST_GETLINE       5 */
  124.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_TEST_GETCHAR       6 */
  125.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_OPEN           7 */
  126.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_READ           8 */
  127.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_WRITE       9 */
  128.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_CLOSE      10 */
  129.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_REMOVE      11 */
  130.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_REMOVE_DIR      12 */
  131.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_MAKE_DIR      13 */
  132.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_CHANGE_DIR      14 */
  133.     { RSNIL /* Proc_Wait */,        RSNIL }, /* SYS_PROC_WAIT      15 */
  134.     { Proc_Detach,            RSNIL }, /* SYS_PROC_DETACH      16 */
  135.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROC_GETIDS      17 */
  136.     { Proc_SetIDs,            RSNIL }, /* SYS_PROC_SETIDS      18 */
  137.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROC_GETGROUPIDS  19 */
  138.     { RSNIL /* Proc_SetGroupIDs */,    RSNIL }, /* SYS_PROC_SETGROUPIDS  20 */
  139.     { Proc_GetFamilyID,            RSNIL }, /* SYS_PROC_GETFAMILYID  21 */
  140.     { Proc_SetFamilyID,            RSNIL }, /* SYS_PROC_SETFAMILYID  22 */
  141.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_TEST_RPC      23 */
  142.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_TEST_STATS      24 */
  143.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_VM_CREATEVA      25 */
  144.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_VM_DESTROYVA      26 */
  145.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_SIG_SEND      27 */
  146.     { RSNIL /* Sig_Pause */,        RSNIL }, /* SYS_SIG_PAUSE      28 */
  147.     { RSNIL /* Sig_SetHoldMask */,    RSNIL }, /* SYS_SIG_SETHOLDMASK   29 */
  148.     { RSNIL /* Sig_SetAction */,    RSNIL }, /* SYS_SIG_SETACTION     30 */
  149.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROF_START      31 */
  150.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROF_END      32 */
  151.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROF_DUMP      33 */
  152.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_VM_CMD              34 */
  153.     { Sys_GetTimeOfDay,            RSNIL }, /* SYS_SYS_GETTIMEOFDAY  35 */
  154.     { Sys_SetTimeOfDay,            RSNIL }, /* SYS_SYS_SETTIMEOFDAY  36 */
  155.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_SYS_DONOTHING     37 */
  156.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROC_GETPCBINFO   38 */
  157.     { RSNIL /* Vm_GetSegInfo */,    RSNIL }, /* SYS_VM_GETSEGINFO     39 */
  158.     { Proc_GetResUsage,            RSNIL }, /* SYS_PROC_GETRESUSAGE  40 */
  159.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROC_GETPRIORITY  41 */
  160.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROC_SETPRIORITY  42 */
  161.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROC_DEBUG      43 */
  162.     { RSNIL /* Not implemented */,    RSNIL }, /* SYS_PROC_PROFILE      44 */
  163.     { RSNIL /* obsolete */,        RSNIL }, /* SYS_FS_TRUNC      45 */
  164.     { RSNIL /* obsolete */,        RSNIL }, /* SYS_FS_TRUNC_ID      46 */
  165.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_GET_NEW_ID      47 */
  166.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_GET_ATTRIBUTES 48 */
  167.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_GET_ATTR_ID      49 */
  168.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_SET_ATTRIBUTES 50 */
  169.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_SET_ATTR_ID      51 */
  170.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_SET_DEF_PERM      52 */
  171.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_IO_CONTROL      53 */
  172.     { Dev_VidEnable,            RSNIL }, /* SYS_SYS_ENABLEDISPLAY 54 */
  173.     { RSNIL /* obsolete */,        RSNIL }, /* SYS_PROC_SET_ENVIRON  55 */
  174.     { RSNIL /* obsolete */,        RSNIL }, /* SYS_PROC_UNSET_ENVIRON 56 */
  175.     { RSNIL /* obsolete */,        RSNIL }, /* SYS_PROC_GET_ENVIRON_VAR 57 */
  176.     { RSNIL /* obsolete */,        RSNIL }, /* SYS_PROC_GET_ENVIRON_RANGE 58 */
  177.     { RSNIL /* obsolete */,          RSNIL }, /* SYS_PROC_INSTALL_ENVIRON 59 */
  178.     { RSNIL /* obsolete */,        RSNIL }, /* SYS_PROC_COPY_ENVIRON 60 */
  179.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_SYNC_SLOWLOCK       61 */
  180.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_SYNC_SLOWWAIT     62 */
  181.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_SYNC_SLOWBROADCAST 63 */
  182.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_VM_PAGESIZE       64 */
  183.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_HARDLINK       65 */
  184.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_RENAME         66 */
  185.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_SYMLINK        67 */
  186.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_READLINK       68 */
  187.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_CREATEPIPE     69 */
  188.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_VM_MAPKERNELINTOUSER 70 */
  189.     { Fs_AttachDiskStub,        RSNIL }, /* SYS_FS_ATTACH_DISK    71 */
  190.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_SELECT         72 */
  191.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_SYS_SHUTDOWN      73 */
  192.     { Proc_Migrate,            RSNIL }, /* SYS_PROC_MIGRATE      74 */
  193.     { Fs_MakeDeviceStub,        RSNIL }, /* SYS_FS_MAKE_DEVICE    75 */
  194.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_COMMAND        76 */
  195.     { RSNIL /* obsolete */,        RSNIL }, /* SYS_FS_LOCK          77 */
  196.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_GETMACHINEINFO    78 */
  197.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_NET_INSTALL_ROUTE 79 */
  198.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_READVECTOR      80 */
  199.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_WRITEVECTOR      81 */
  200.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_CHECKACCESS    82 */
  201.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROC_GETINTERVALTIMER  83 */
  202.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROC_SETINTERVALTIMER  84 */
  203.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_WRITEBACKID    85 */
  204.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROC_EXEC_ENV     86 */
  205.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_SET_ATTR_NEW   87 */
  206.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_SET_ATTR_ID_NEW 88 */
  207.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROC_GETHOSTIDS   89 */
  208.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_SCHED_IDLE_PROCESSOR 90 */
  209.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_SCHED_START_PROCESSOR 91 */
  210.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_MACH_NUM_PROCESSORS 92 */
  211.     { RSNIL /* Not migrated */,         RSNIL }, /* SYS_PROF_PROFIL 93 */
  212.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROC_REMOTE_EXEC     94 */
  213.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_SYS_GETMACHINEINFO_NEW  95 */
  214.     { RSNIL /* Not migrated */,        RSNIL},  /* VM_MMAP 96 */
  215.     { RSNIL /* Not migrated */,        RSNIL},  /* VM_MUNMAP 97 */
  216.     { RSNIL /* Not migrated */,        RSNIL},  /* VM_MSYNC 98 */
  217.     { RSNIL /* Not migrated */,        RSNIL},  /* VM_MLOCK 99 */
  218.     { RSNIL /* Not migrated */,        RSNIL},  /* VM_MUNLOCK 100 */
  219.     { RSNIL /* Not migrated */,        RSNIL},  /* VM_MINCORE 101 */
  220.     { RSNIL /* Not migrated */,        RSNIL},  /* SYNC_SEMCTL 102 */
  221.     { RSNIL /* Not migrated */,        RSNIL},  /* SYNC_SEMGET 103 */
  222.     { RSNIL /* Not migrated */,        RSNIL},  /* SYNC_SEMOP 104 */
  223.     { RSNIL /* Not migrated */,        RSNIL},  /* VM_MPROTECT 105 */
  224.     { RpcProcFork,            RSNIL }, /* SYS_PROC_VFORK 106 */
  225.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_NET_GET_ROUTES 107 */
  226.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_NET_DELETE_ROUTE 108 */
  227.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_ZSS_CMD 109 */
  228.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_ZEBRA_CMD 110 */
  229.     { Sys_GetHostName,            RSNIL }, /* SYS_GET_HOSTNAME 111 */
  230.     { Sys_SetHostName,            RSNIL }, /* SYS_SET_HOSTNAME 112 */
  231.  
  232. };
  233.  
  234.  
  235. /*
  236.  * Define an array of callbacks to do when handling migration commands.
  237.  * Each of these procedures is called with the following arguments:
  238.  *
  239.  *    func(cmdPtr, procPtr, inBufSize, inBufPtr, outBufSizePtr,
  240.  *          outBufPtrPtr)
  241.  *
  242.  * cmdPtr is a pointer to a ProcMigCommand structure containing the
  243.  * processID of the process on this host, and the input and output
  244.  * buffers are dependent on the command.  The output buffer arguments
  245.  * may be left alone, or set to point to a newly allocated buffer.
  246.  * procPtr is generally a pointer to a locked control block for the
  247.  * process being operated on, or is NIL in the case of
  248.  * ProcMigAcceptMigration creating a new process.
  249.  */
  250. static PRS commandCallbacks[] = {
  251.     ProcMigAcceptMigration,
  252.     ProcMigReceiveProcess,
  253.     ProcMigGetUpdate,
  254.     ProcMigEncapCallback,
  255.     ProcMigDestroyCmd,
  256.     ProcMigContinueProcess,
  257.     ProcMigGetSuspend,
  258. };
  259.  
  260.  
  261.  
  262.  
  263. /*
  264.  *----------------------------------------------------------------------
  265.  *
  266.  * RpcRemoteCall --
  267.  *
  268.  *    Service a system call for a migrated process.  Call the rpc
  269.  *    module to return the results, if any.
  270.  *
  271.  * Results:
  272.  *    Any data retured by the system call is passed back in a buffer,
  273.  *    as is its length.  The result returned by the system call is
  274.  *    returned as the ReturnStatus for this procedure.
  275.  *
  276.  * Side effects:
  277.  *    None.
  278.  *
  279.  *----------------------------------------------------------------------
  280.  */
  281.  
  282. /* ARGSUSED */
  283. static ReturnStatus
  284. RpcRemoteCall(callPtr, dataPtr, dataLength, replyDataPtr,
  285.            replyDataLengthPtr)
  286.     Proc_RemoteCall *callPtr;
  287.     Address dataPtr;
  288.     int dataLength;
  289.     Address *replyDataPtr;
  290.     int *replyDataLengthPtr;
  291. {
  292.     register Proc_ControlBlock *procPtr;
  293.     ReturnStatus status;
  294.     Sys_ArgArray args;
  295.     int disp;
  296.     int size;
  297.     int paddedSize;
  298.     Address inputPtr;
  299.     Address outputPtr;
  300.     int i;
  301.     Proc_TraceRecord record;
  302.  
  303.     if (proc_MigDebugLevel > 4) {
  304.     printf("Proc_RpcRemoteCall(%d) called.\n", callPtr->callNumber);
  305.     }
  306.  
  307.     *replyDataLengthPtr = 0;
  308.     *replyDataPtr = (Address) NIL;
  309.  
  310.     /*
  311.      * It's possible for an exit to come in while a process is in the NEW
  312.      * state if an error occurs while migrating it back home.  In this case,
  313.      * allow an exit to come in.  Otherwise, be more particular about which
  314.      * processIDs correspond to valid shadow processes.
  315.      */
  316.     procPtr = Proc_LockPID(callPtr->processID);
  317.     if (procPtr == (Proc_ControlBlock *) NIL
  318.     || ((procPtr->state != PROC_MIGRATED) &&
  319.         !((procPtr->state == PROC_NEW) &&
  320.           (callPtr->callNumber == SYS_PROC_EXIT)))) {
  321.     if ((procPtr != (Proc_ControlBlock *) NIL) &&
  322.         (procPtr->genFlags & PROC_MIGRATION_DONE)) {
  323.         /*
  324.          * Migration is complete, but it hasn't context switched yet.
  325.          * This is okay, since nothing it does after that point
  326.          * affects the process.  But, if the call is EXIT, flag an error.
  327.          */
  328.         if (callPtr->callNumber == SYS_PROC_EXIT) {
  329.         procPtr->genFlags |= PROC_MIG_ERROR;
  330.         Proc_Unlock(procPtr);
  331.         return(SUCCESS);
  332.         }
  333.     } else {
  334.         printf("Warning: Proc_RpcRemoteCall: invalid pid: %x.\n",
  335.            callPtr->processID);
  336.         if (procPtr != (Proc_ControlBlock *) NIL) {
  337.         printf("Proc_RpcRemoteCall: state = %d, call = %d.\n",
  338.                (int) procPtr->state, callPtr->callNumber);
  339.         Proc_Unlock(procPtr);
  340.         }
  341.         /*
  342.          * Return a special status that indicates the migrated process
  343.          * should be destroyed.
  344.          */
  345.         return (PROC_NO_PEER);
  346.     }
  347.     }
  348.     Proc_Unlock(procPtr);
  349.     if (callBackVector[callPtr->callNumber].localPtr ==
  350.         (ReturnStatus (*) ()) NIL) {
  351.      panic("Proc_RpcRemoteCall: can't handle call %d.\n",
  352.           callPtr->callNumber);
  353.     return(SYS_INVALID_SYSTEM_CALL);
  354.     }
  355.  
  356.     /*
  357.      * Set the effective process for this processor.
  358.      */
  359.  
  360.     Proc_SetEffectiveProc(procPtr);
  361.  
  362.     if (proc_DoTrace && proc_DoCallTrace) {
  363.     record.processID = callPtr->processID;
  364.     record.flags = PROC_MIGTRACE_START | PROC_MIGTRACE_HOME;
  365.     record.info.call.callNumber = callPtr->callNumber;
  366.     Trace_Insert(proc_TraceHdrPtr, PROC_MIGTRACE_CALL,
  367.              (ClientData) &record);
  368.     }
  369.  
  370.     if (!callPtr->parseArgs) {
  371.     status = (*(callBackVector[callPtr->callNumber].localPtr))
  372.         (procPtr, dataPtr, dataLength, replyDataPtr,
  373.          replyDataLengthPtr);
  374.     if (proc_MigDebugLevel > 4) {
  375.         printf("Proc_RpcRemoteCall: unparsed call %d returned %x.\n",
  376.                callPtr->callNumber, status);
  377.     }
  378.  
  379.     if (proc_DoTrace && proc_DoCallTrace) {
  380.         record.info.call.status = status;
  381.         record.flags &= ~PROC_MIGTRACE_START;
  382.         Trace_Insert(proc_TraceHdrPtr, PROC_MIGTRACE_CALL,
  383.              (ClientData) &record);
  384.     }
  385.     Proc_SetEffectiveProc((Proc_ControlBlock *) NIL);
  386.     return(status);
  387.     }
  388.  
  389.     *replyDataPtr = (Address) malloc(callPtr->replySize);
  390.     *replyDataLengthPtr = callPtr->replySize;
  391.     outputPtr = *replyDataPtr;
  392.     inputPtr = dataPtr;
  393.  
  394.     for (i = 0; i < callPtr->numArgs; i++) {
  395.     disp = callPtr->info[i].disposition;
  396.     size = callPtr->info[i].size;
  397.     paddedSize = Byte_AlignAddr(size);
  398.     if (disp & (SYS_PARAM_ACC | SYS_PARAM_COPY)) {
  399.         if (disp & SYS_PARAM_NIL) {
  400.         args.argArray[i] = USER_NIL;
  401.         } else if (disp & SYS_PARAM_OUT) {
  402.         if (disp & SYS_PARAM_IN) {
  403.             bcopy(inputPtr, outputPtr, size);
  404.             inputPtr += paddedSize;
  405.         }
  406.         args.argArray[i] = (int) outputPtr;
  407.         outputPtr += paddedSize;
  408.         } else {
  409.         args.argArray[i] = (int) inputPtr;
  410.         inputPtr += paddedSize;
  411.         }
  412.     } else {
  413.         if (size != sizeof(int)) {
  414.         panic("Proc_RpcRemoteCall: size mismatch.\n");
  415.         }
  416.         args.argArray[i] = * ((int *)inputPtr);
  417.         inputPtr += paddedSize;
  418.     }
  419.     }
  420.  
  421.     status = (*(callBackVector[callPtr->callNumber].localPtr)) (args);
  422.     if (proc_MigDebugLevel > 4) {
  423.      printf("Proc_RpcRemoteCall: parsed call %d returned %x.\n",
  424.            callPtr->callNumber, status);
  425.     }
  426.     Proc_SetEffectiveProc((Proc_ControlBlock *) NIL);
  427.  
  428.     if (proc_DoTrace && proc_DoCallTrace) {
  429.     record.info.call.status = status;
  430.     record.flags &= ~PROC_MIGTRACE_START;
  431.     Trace_Insert(proc_TraceHdrPtr, PROC_MIGTRACE_CALL,
  432.              (ClientData) &record);
  433.     }
  434.  
  435.     return(status);
  436. }
  437.  
  438.  
  439. /*
  440.  *----------------------------------------------------------------------
  441.  *
  442.  * RpcProcExit --
  443.  *
  444.  *    Perform an exit on the home node of a process.
  445.  *
  446.  * Results:
  447.  *    SUCCESS         - the process exited successfully.
  448.  *    PROC_INVALID_PID     - the process does not exist.
  449.  *
  450.  * Side effects:
  451.  *    None.
  452.  *
  453.  *----------------------------------------------------------------------
  454.  */
  455.  
  456. /* ARGSUSED */
  457. static ReturnStatus
  458. RpcProcExit(procPtr, dataPtr, dataLength, replyDataPtr,
  459.            replyDataLengthPtr)
  460.     register Proc_ControlBlock *procPtr;
  461.     Address dataPtr;
  462.     int dataLength;
  463.     Address *replyDataPtr;
  464.     int *replyDataLengthPtr;
  465. {
  466.     Timer_Ticks kernelTicks;
  467.     Timer_Ticks userTicks;
  468.     int count;
  469.     int reason;    /* Why the process is dying: EXITED, SIGNALED, DESTROYED  */
  470.     int    status;    /* Exit status or signal # or destroy status */
  471.     int code;    /* Signal sub-status */
  472.     Proc_PID pid;
  473.  
  474.     if (proc_MigDebugLevel > 4) {
  475.     printf("RpcProcExit called.\n");
  476.     }
  477.  
  478.     Proc_Lock(procPtr);
  479.     Byte_EmptyBuffer(dataPtr, Timer_Ticks,  kernelTicks);
  480.     Timer_AddTicks(procPtr->kernelCpuUsage.ticks, kernelTicks,
  481.            &procPtr->kernelCpuUsage.ticks);
  482.     Byte_EmptyBuffer(dataPtr, Timer_Ticks,  userTicks);
  483.     Timer_AddTicks(procPtr->userCpuUsage.ticks, userTicks,
  484.            &procPtr->userCpuUsage.ticks);
  485. #ifndef CLEAN
  486.     /*
  487.      * Record the remote usage for this process.  Note that the usage is
  488.      * also recorded in the total usage for this host under ProcExitProcess.
  489.      */
  490.     Timer_AddTicks(kernelTicks, userTicks, &userTicks);
  491.     ProcRecordUsage(userTicks, PROC_MIG_USAGE_REMOTE_CPU);
  492. #endif /* CLEAN */
  493.  
  494.     Byte_EmptyBuffer(dataPtr, int,  count);
  495.     procPtr->numQuantumEnds += count;
  496.     Byte_EmptyBuffer(dataPtr, int, count);
  497.     procPtr->numWaitEvents += count;
  498.  
  499.     Byte_EmptyBuffer(dataPtr, int, reason);
  500.     Byte_EmptyBuffer(dataPtr, int, status);
  501.     Byte_EmptyBuffer(dataPtr, int, code);
  502.  
  503.  
  504.     pid = procPtr->processID;
  505.  
  506.     /*
  507.      * Perform an exit on behalf of the process.  The process is
  508.      * unlocked as a side effect.
  509.      */
  510.     ProcExitProcess(procPtr, reason, status, code, FALSE);
  511.  
  512.     /*
  513.      * Remove the dependency on the other host.
  514.      */
  515.     ProcMigRemoveDependency(pid, TRUE);
  516.  
  517.     /*
  518.      * Update statistics.
  519.      */
  520. #ifndef CLEAN
  521.     if (proc_MigDoStats) {
  522.     PROC_MIG_DEC_STAT(remote);
  523.     }
  524. #endif /* CLEAN */   
  525.  
  526.     if (proc_MigDebugLevel > 4) {
  527.     printf("RpcProcExit returning SUCCESS.\n");
  528.     }
  529.     return(SUCCESS);
  530. }
  531.  
  532.  
  533. /*
  534.  *----------------------------------------------------------------------
  535.  *
  536.  * RpcProcExec --
  537.  *
  538.  *    Perform an exec on the home node of a process.
  539.  *
  540.  * Results:
  541.  *    SUCCESS         - The process is migrated and has been
  542.  *                   modified.
  543.  *
  544.  * Side effects:
  545.  *    the process's argument string and effective userID are modified.
  546.  *
  547.  *----------------------------------------------------------------------
  548.  */
  549.  
  550. /* ARGSUSED */
  551. static ReturnStatus
  552. RpcProcExec(procPtr, dataPtr, dataLength, replyDataPtr,
  553.            replyDataLengthPtr)
  554.     register Proc_ControlBlock *procPtr;
  555.     Address dataPtr;
  556.     int dataLength;
  557.     Address *replyDataPtr;
  558.     int *replyDataLengthPtr;
  559. {
  560.     int uid;
  561.     char *argString;
  562.  
  563.     if (proc_MigDebugLevel > 4) {
  564.     printf("RpcProcExec called.\n");
  565.     }
  566.  
  567.     Proc_Lock(procPtr);
  568.     Byte_EmptyBuffer(dataPtr, int, uid);
  569.     if (uid != -1) {
  570.     procPtr->effectiveUserID = uid;
  571.     }
  572.     /*
  573.      * The data area contains the uid followed by the argString. Therefore,
  574.      * we allocate space equal to the data length - 1.  (The null terminator
  575.      * is included in the string passed over).
  576.      */
  577.     argString = malloc(dataLength - 1);
  578.     if (procPtr->argString != (char *) NIL) {
  579.     free(procPtr->argString);
  580.     }
  581.     procPtr->argString = argString;
  582.     (void) strcpy(argString, dataPtr);
  583.  
  584.     if (proc_MigDebugLevel > 6) {
  585.     printf("RpcProcExec setting argString to '%s'.\n", argString);
  586.     }
  587.  
  588.  
  589.     Proc_Unlock(procPtr);
  590.  
  591.     if (proc_MigDebugLevel > 4) {
  592.     printf("RpcProcExec returning SUCCESS.\n");
  593.     }
  594.     return(SUCCESS);
  595. }
  596.  
  597.  
  598. /*
  599.  *----------------------------------------------------------------------
  600.  *
  601.  * RpcProcFork --
  602.  *
  603.  *    Perform a fork on the home node of a process.  This involves allocating
  604.  *    a PCB and process ID for the process, and copying certain local
  605.  *    information such as the environment.
  606.  *
  607.  * Results:
  608.  *    SUCCESS         - the process forked successfully.
  609.  *    PROC_INVALID_PID     - the process does not exist.
  610.  *
  611.  * Side effects:
  612.  *    A new process is created.  The identifier of the newly-created
  613.  *    process is returned to the remote node in the data buffer.
  614.  *
  615.  *----------------------------------------------------------------------
  616.  */
  617.  
  618. /* ARGSUSED */
  619. static ReturnStatus
  620. RpcProcFork(parentProcPtr, dataPtr, dataLength, replyDataPtr,
  621.         replyDataLengthPtr)
  622.     register Proc_ControlBlock *parentProcPtr;
  623.     Address dataPtr;
  624.     int dataLength;
  625.     Address *replyDataPtr;
  626.     int *replyDataLengthPtr;
  627. {
  628.     Proc_ControlBlock     *childProcPtr;    /* The new process being created */
  629.  
  630.     if (proc_MigDebugLevel > 3) {
  631.     printf("RpcProcFork called.\n");
  632.     }
  633.     childProcPtr = ProcGetUnusedPCB();
  634.  
  635.     childProcPtr->Prof_Scale = 0;
  636.     Prof_Enable(childProcPtr, parentProcPtr->Prof_Buffer, 
  637.         parentProcPtr->Prof_BufferSize, parentProcPtr->Prof_Offset,
  638.     parentProcPtr->Prof_Scale);
  639.  
  640.     childProcPtr->state         = PROC_MIGRATED;
  641.     childProcPtr->genFlags            |= PROC_USER | PROC_NO_VM;
  642.     childProcPtr->syncFlags        = 0;
  643.     childProcPtr->schedFlags        = 0;
  644.     childProcPtr->exitFlags        = 0;
  645.  
  646.     childProcPtr->billingRate     = parentProcPtr->billingRate;
  647.     childProcPtr->recentUsage     = 0;
  648.     childProcPtr->weightedUsage     = 0;
  649.     childProcPtr->unweightedUsage     = 0;
  650.  
  651.     childProcPtr->kernelCpuUsage.ticks     = timer_TicksZeroSeconds;
  652.     childProcPtr->userCpuUsage.ticks         = timer_TicksZeroSeconds;
  653.     childProcPtr->childKernelCpuUsage.ticks     = timer_TicksZeroSeconds;
  654.     childProcPtr->childUserCpuUsage.ticks     = timer_TicksZeroSeconds;
  655.     childProcPtr->numQuantumEnds    = 0;
  656.     childProcPtr->numWaitEvents    = 0;
  657.  
  658.     childProcPtr->parentID         = parentProcPtr->processID;
  659.     childProcPtr->userID         = parentProcPtr->userID;
  660.     childProcPtr->effectiveUserID     = parentProcPtr->effectiveUserID;
  661.     childProcPtr->familyID         = parentProcPtr->familyID;
  662.  
  663.     if (childProcPtr->argString != (char *) NIL) {
  664.     free(childProcPtr->argString);
  665.     }
  666.     if (parentProcPtr->argString != (Address) NIL) {
  667.     childProcPtr->argString =
  668.         (char *) malloc(strlen(parentProcPtr->argString) + 1);
  669.     (void) strcpy(childProcPtr->argString, parentProcPtr->argString);
  670.     } else {
  671.     childProcPtr->argString    = (char *) NIL;
  672.     }
  673.  
  674.  
  675.     Vm_ProcInit(childProcPtr);
  676.  
  677.     if (ProcFamilyInsert(childProcPtr, childProcPtr->familyID) != SUCCESS) {
  678.     panic("RpcProcFork: ProcFamilyInsert failed\n");
  679.     }
  680.  
  681.     /*
  682.      *  Initialize our child list to remove any old links.
  683.      *  Insert this PCB entry into the list of children of our parent.
  684.      */
  685.     List_Init((List_Links *) childProcPtr->childList);
  686.     List_Insert((List_Links *) &(childProcPtr->siblingElement),
  687.         LIST_ATREAR(parentProcPtr->childList));
  688.  
  689.     Sig_Fork(parentProcPtr, childProcPtr);
  690.  
  691.     /*
  692.      * Initialize information for migration.
  693.      */
  694.  
  695.     Byte_EmptyBuffer(dataPtr, Proc_PID, childProcPtr->peerProcessID);
  696.     childProcPtr->peerHostID = parentProcPtr->peerHostID;
  697.  
  698.     /*
  699.      * Set up the environment of the process.
  700.      */
  701.  
  702.      ProcSetupEnviron(childProcPtr);
  703.  
  704.     /*
  705.      * Have the new process inherit filesystem state.
  706.      */
  707.     Fs_InheritState(parentProcPtr, childProcPtr);
  708.  
  709.     /*
  710.      * Note the dependency of the new process on the other host.
  711.      */
  712.     ProcMigAddDependency(childProcPtr->processID, childProcPtr->peerProcessID);
  713.  
  714.     /*
  715.      * Update statistics.
  716.      */
  717. #ifndef CLEAN
  718.     if (proc_MigDoStats) {
  719.     PROC_MIG_INC_STAT(remote);
  720.     }
  721. #endif /* CLEAN */   
  722.  
  723.     /*
  724.      * Send back the child's process ID in the replyData buffer.
  725.      */
  726.  
  727.     *replyDataLengthPtr = sizeof(Proc_PID);
  728.     *replyDataPtr = (Address) malloc(sizeof(Proc_PID));
  729.     * ((Proc_PID *) *replyDataPtr) = childProcPtr->processID;
  730.  
  731.     if (proc_MigDebugLevel > 3) {
  732.     printf("RpcProcFork returning SUCCESS.\n");
  733.     }
  734.  
  735.     Proc_Unlock(childProcPtr);
  736.     return(SUCCESS);
  737. }
  738.  
  739.  
  740. /*
  741.  *----------------------------------------------------------------------
  742.  *
  743.  * Proc_ByteCopy --
  744.  *
  745.  *    Perform a copy into or out of the user's address space.  If
  746.  *    the user process is migrated, copy the arguments directly and
  747.  *    let the rpc server send the results to the remote node.
  748.  *
  749.  * Results:
  750.  *    SUCCESS         - the copy was performed successfully.
  751.  *    SYS_ARG_NOACCESS     - the argument was not accessible.
  752.  *
  753.  * Side effects:
  754.  *    None.
  755.  *
  756.  *----------------------------------------------------------------------
  757.  */
  758.  
  759. ReturnStatus
  760. Proc_ByteCopy(copyIn, numBytes, sourcePtr, destPtr)
  761.     Boolean copyIn;        /* copy into or out of kernel address space */
  762.     int numBytes;        /* The number of bytes to copy */
  763.     Address sourcePtr;        /* Where to copy from */
  764.     Address destPtr;        /* Where to copy to */
  765. {
  766.     ReturnStatus status = SUCCESS;
  767.  
  768.     if (Proc_UseRpcBuffer()) {
  769.     bcopy(sourcePtr, destPtr, numBytes);
  770.     } else if (copyIn) {
  771.     status = Vm_CopyIn(numBytes, sourcePtr, destPtr);
  772.     } else {
  773.     status = Vm_CopyOut(numBytes, sourcePtr, destPtr);
  774.     }
  775.     return(status);
  776. }
  777.  
  778.  
  779. /*
  780.  *----------------------------------------------------------------------
  781.  *
  782.  * Proc_StringNCopy --
  783.  *
  784.  *    Copy a string from the user's address space to a buffer of 
  785.  *    limited length.  If the user process is a ghost (an RPC that 
  786.  *    was migrated home), copy the argument directly.  cf. 
  787.  *    Proc_ByteCopy and Vm_StringNCopy.
  788.  *
  789.  * Results:
  790.  *    SUCCESS
  791.  *
  792.  * Side effects:
  793.  *    *strNameLength is set to the actual length of the string copied.
  794.  *
  795.  *----------------------------------------------------------------------
  796.  */
  797.  
  798. ReturnStatus
  799. Proc_StringNCopy(numBytes, srcStr, destStr, strLengthPtr)
  800.     register int    numBytes;    /* Maximum number of bytes to copy. */
  801.     register char    *srcStr;    /* String to copy. */
  802.     register char    *destStr;    /* Where to copy string to. */
  803.     int            *strLengthPtr;    /* Where to return actual length of
  804.                      * string copied. */
  805. {
  806.     register int length;
  807.     ReturnStatus status;
  808.  
  809.     if (!Proc_UseRpcBuffer()) {
  810.     status =  Vm_StringNCopy(numBytes, srcStr, destStr,
  811.                  strLengthPtr);
  812.     } else {
  813.     for (length = 0; (length < numBytes) && (*srcStr != '\0'); length++) {
  814.         *destStr++ = *srcStr++;
  815.     }
  816.     *destStr = '\0';
  817.     *strLengthPtr = length;
  818.     status = SUCCESS;
  819.     }
  820.  
  821. #if PARANOIA
  822.     /* 
  823.      * If the copy succeeded, check whether it should have.  This test used 
  824.      * to come first, but then it would cause panics if someone passed in a 
  825.      * null pointer.
  826.      */
  827.     if (procStringChecks && status == SUCCESS) {
  828.     if (!Proc_UseRpcBuffer() && !IsUserAddr(srcStr)) {
  829.         panic("Proc_StringNCopy: copying from kernel address 0x%x\n",
  830.           srcStr);
  831.     }
  832.     if (IsUserAddr(destStr)) {
  833.         panic("Proc_StringNCopy: copying to user address 0x%x\n",
  834.           destStr);
  835.     }
  836.     }
  837. #endif
  838.  
  839.     return status;
  840. }
  841.  
  842.  
  843.  
  844. /*
  845.  *----------------------------------------------------------------------
  846.  *
  847.  * Proc_MakeStringAccessible --
  848.  *
  849.  *    If the string is in user space, convert the user space path pointer
  850.  *    into a kernel valid pointer.  If the string is in kernel space
  851.  *    already (i.e., a system call is being performed on behalf of a
  852.  *    migrated process), do nothing.
  853.  *
  854.  *
  855.  * Results:
  856.  *    SYS_ARG_NOACCESS    - the Vm_MakeAccessible call failed.
  857.  *    PROC_INVALID_STRING - the length of the string exceeds the maximum
  858.  *                          permissible length or is not null-terminated.
  859.  *
  860.  *    The new pointer is returned in *stringPtrPtr.  The length of the
  861.  *    string is returned in *newLengthPtr if newLengthPtr is non-NIL.
  862.  *
  863.  * Side effects:
  864.  *    Make an area of the user code accessible.
  865.  *
  866.  *----------------------------------------------------------------------
  867.  */
  868. ReturnStatus
  869. Proc_MakeStringAccessible(maxLength, stringPtrPtr, accessLengthPtr,
  870.               newLengthPtr)
  871.     int maxLength;     /* Maximum allowable string length */
  872.     char **stringPtrPtr; /* On input *stringPtrPtr is a user space pointer,
  873.               * On output *stringPtrPtr is a kernel space pointer */
  874.     int *accessLengthPtr;/* Number of bytes actually made accessible. */
  875.     int *newLengthPtr;     /* length of the string that is made accessible */
  876. {
  877.     int accessLength = maxLength;
  878.     register int realLength;
  879.     Boolean madeAccessible = FALSE;
  880.     register char *charPtr;
  881.  
  882.     if (!Proc_UseRpcBuffer()) {
  883.     Vm_MakeAccessible(VM_READONLY_ACCESS,
  884.               maxLength, (Address) *stringPtrPtr,
  885.               &accessLength, (Address *) stringPtrPtr);
  886.     if (*stringPtrPtr == (Address)NIL) {
  887.         return(SYS_ARG_NOACCESS);
  888.     }
  889.     madeAccessible = TRUE;
  890.     *accessLengthPtr = accessLength;
  891.     }
  892.     /*
  893.      * Do a length check.  If the file name takes up all the addressable
  894.      * space then it isn't null terminated and will cause problems later.
  895.      */
  896.     for (charPtr = *stringPtrPtr, realLength = 0;
  897.      (realLength < accessLength) && (*charPtr != '\0');
  898.      charPtr++, realLength++) {
  899.      }
  900.     if (realLength == accessLength && *charPtr != '\0') {
  901.     if (madeAccessible) {
  902.         Vm_MakeUnaccessible((Address) *stringPtrPtr, accessLength);
  903.     }
  904.     *stringPtrPtr = (Address)NIL;
  905.     return(PROC_INVALID_STRING);
  906.     }
  907.     if (newLengthPtr != (int *) NIL) {
  908.     *newLengthPtr = realLength;
  909.     }
  910.     return(SUCCESS);
  911. }
  912.  
  913.  
  914. /*
  915.  *----------------------------------------------------------------------
  916.  *
  917.  * Proc_MakeUnaccessible
  918.  *
  919.  *    If the pointer is to something that was made accessible as a
  920.  *    result of a local system call, call Vm_MakeUnaccessible.  
  921.  *    Otherwise, the pointer is to a (kernel) RPC buffer and should 
  922.  *    be left alone.  This routine is used by generic system call
  923.  *    stubs that may be called either locally or on behalf of a
  924.  *    ghost process.
  925.  *
  926.  * Results:
  927.  *    None.
  928.  *
  929.  * Side effects:
  930.  *    Kernel page table may be modified.
  931.  *
  932.  *----------------------------------------------------------------------
  933.  */
  934. void
  935. Proc_MakeUnaccessible(addr, numBytes)
  936.     Address        addr;
  937.     int            numBytes;
  938. {
  939.  
  940.     if (!Proc_UseRpcBuffer()) {
  941.     Vm_MakeUnaccessible(addr, numBytes);
  942.     }
  943. }
  944.  
  945.  
  946. /*
  947.  *----------------------------------------------------------------------
  948.  *
  949.  * Proc_RpcRemoteWait --
  950.  *
  951.  *    Perform a Proc_Wait on behalf of a migrated process.
  952.  *
  953.  * Results:
  954.  *    SUCCESS - an exiting/detached child was found and the information
  955.  *          about it is being returned.
  956.  *    PROC_NO_EXITS - No children have performed an exit or detach
  957.  *                (except possibly children about whom the parent has
  958.  *            already been notified).
  959.  *
  960.  * Side effects:
  961.  *    If the process has no exiting children and it has specified that
  962.  *    it should block until a child exits, the process is established
  963.  *    as performing a remote wait.
  964.  *
  965.  *----------------------------------------------------------------------
  966.  */
  967.  
  968. /* ARGSUSED */
  969. ReturnStatus
  970. Proc_RpcRemoteWait(srvToken, clientID, command, storagePtr)
  971.     ClientData srvToken;    /* Handle on server process passed to
  972.                  * Rpc_Reply */
  973.     int clientID;        /* Sprite ID of client host */
  974.     int command;        /* Command identifier */
  975.     Rpc_Storage *storagePtr;    /* The request fields refer to the request
  976.                  * buffers and also indicate the exact amount
  977.                  * of data in the request buffers.  The reply
  978.                  * fields are initialized to NIL for the
  979.                  * pointers and 0 for the lengths.  This can
  980.                  * be passed to Rpc_Reply */
  981. {
  982.     ReturnStatus status;
  983.     ProcChildInfo *childInfoPtr;
  984.     register ProcRemoteWaitCmd *cmdPtr;
  985.     Proc_PID *pidArray;
  986.     Rpc_ReplyMem *replyMemPtr;
  987.     Proc_ControlBlock *procPtr;
  988.  
  989.     if (proc_MigDebugLevel > 3) {
  990.     printf("Proc_RpcRemoteWait entered.\n");
  991.  
  992.     }
  993.  
  994.     cmdPtr = (ProcRemoteWaitCmd *) storagePtr->requestParamPtr;
  995.     procPtr = Proc_LockPID(cmdPtr->pid);
  996.  
  997.     if (procPtr == (Proc_ControlBlock *) NIL) {
  998.     if (proc_MigDebugLevel > 1) {
  999.         printf("Proc_RpcRemoteWait: no such process %x\n", cmdPtr->pid);
  1000.     }
  1001.     return (PROC_NO_PEER);
  1002.     } else {
  1003.     status = WaitSanityChecks(procPtr, clientID);
  1004.     if (status != SUCCESS) {
  1005.         Proc_Unlock(procPtr);
  1006.         return (status);
  1007.     }
  1008.     }
  1009.  
  1010.     /* 
  1011.      * If the local process is still finishing up migration, wait for it to 
  1012.      * complete. 
  1013.      */
  1014.     if (procPtr->state != PROC_MIGRATED) {
  1015.     if (proc_MigDebugLevel > 2) {
  1016.         printf("%s: waiting for process %x to context switch.\n",
  1017.            "Proc_RpcRemoteWait", procPtr->processID);
  1018.     }
  1019.     Proc_Unlock(procPtr);
  1020.     status = Proc_WaitForMigration(cmdPtr->pid);
  1021.     if (status != SUCCESS) {
  1022.         if (proc_MigDebugLevel > 1) {
  1023.         printf("%s: error waiting for pid %x to context switch.\n",
  1024.                "Proc_RpcRemoteWait", cmdPtr->pid);
  1025.         }
  1026.         return (PROC_NO_PEER);
  1027.     }
  1028.     Proc_Lock(procPtr);
  1029.     status = WaitSanityChecks(procPtr, clientID);
  1030.     if (status != SUCCESS) {
  1031.         if (proc_MigDebugLevel > 1) {
  1032.         printf("%s: error after waiting for pid %x to ctxt switch\n",
  1033.                "Proc_RpcRemoteWait", procPtr->processID);
  1034.         }
  1035.         Proc_Unlock(procPtr);
  1036.         return (status);
  1037.     }
  1038.     }
  1039.  
  1040.     pidArray = (Proc_PID *) storagePtr->requestDataPtr;
  1041.     childInfoPtr = (ProcChildInfo *) malloc(sizeof(ProcChildInfo));
  1042.  
  1043.     status = ProcServiceRemoteWait(procPtr, cmdPtr->flags, cmdPtr->numPids,
  1044.                     pidArray, cmdPtr->token,
  1045.                    childInfoPtr);
  1046.  
  1047.     Proc_Unlock(procPtr);
  1048.     if (status == SUCCESS) {
  1049.     storagePtr->replyDataPtr = (Address) childInfoPtr;
  1050.     storagePtr->replyDataSize = sizeof(ProcChildInfo);
  1051.     replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  1052.     replyMemPtr->paramPtr = (Address) NIL;
  1053.     replyMemPtr->dataPtr = storagePtr->replyDataPtr;
  1054.  
  1055.     Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
  1056.         (ClientData) replyMemPtr);
  1057.     } else {
  1058.     free((Address) childInfoPtr);
  1059.     }
  1060.  
  1061.     if (proc_MigDebugLevel > 3) {
  1062.     printf("Proc_RpcRemoteWait: returning %x.\n", status);
  1063.     }
  1064.     return(status);
  1065. }
  1066.  
  1067.  
  1068. /*
  1069.  *----------------------------------------------------------------------
  1070.  *
  1071.  * WaitSanityChecks --
  1072.  *
  1073.  *    Do some sanity checks for the remote wait() call on the given 
  1074.  *    locked PCB.
  1075.  *
  1076.  * Results:
  1077.  *    Returns a Sprite status code.
  1078.  *
  1079.  * Side effects:
  1080.  *    None.
  1081.  *
  1082.  *----------------------------------------------------------------------
  1083.  */
  1084.  
  1085. static ReturnStatus
  1086. WaitSanityChecks(procPtr, clientID)
  1087.     Proc_ControlBlock *procPtr;
  1088.     int clientID;        /* host that made the wait request */
  1089. {
  1090.     /* 
  1091.      * Verify that the process is migrated and that the process's remote
  1092.      * host is the one making the wait request.
  1093.      */
  1094.     if (!IsMigrated(procPtr) || procPtr->peerHostID != clientID) {
  1095.     if (proc_MigDebugLevel > 1) {
  1096.         if (procPtr->peerHostID != clientID) {
  1097.         printf("%s: process %x has peer host %d, expected %d.\n",
  1098.                "Proc_RpcRemoteWait", procPtr->processID,
  1099.                procPtr->peerHostID, clientID);
  1100.         } else {
  1101.         printf("%s: process %x not migrated (state %d, flags 0x%x)\n",
  1102.                "Proc_RpcRemoteWait", procPtr->processID,
  1103.                procPtr->state, procPtr->genFlags);
  1104.         }
  1105.     }
  1106.     return(PROC_NO_PEER);
  1107.     }
  1108.  
  1109.     return(SUCCESS);
  1110. }
  1111.  
  1112.  
  1113. /*
  1114.  *----------------------------------------------------------------------
  1115.  *
  1116.  * Proc_RpcMigCommand --
  1117.  *
  1118.  *    Handle a request regarding process migration.  This may be a
  1119.  *    request to initiate migration, a buffer containing part or all
  1120.  *    of the encapsulated state of a process, a callback by another
  1121.  *    module during state transfer, or a command to asynchronously
  1122.  *    kill a migrated process due to some error.
  1123.  *
  1124.  * Results:
  1125.  *    SUCCESS is returned to the rpc daemon invoking this procedure.
  1126.  *    Various ReturnStatus values may be returned via the RPC itself.
  1127.  *    It is either SUCCESS or some error returned by a lower level routine
  1128.  *    (e.g., no such process). In addition, the called routine may
  1129.  *    return arbitrary data.
  1130.  *
  1131.  * Side effects:
  1132.  *    Variable (see above).
  1133.  *
  1134.  *----------------------------------------------------------------------
  1135.  */
  1136. /*ARGSUSED*/
  1137. ReturnStatus
  1138. Proc_RpcMigCommand(srvToken, hostID, command, storagePtr)
  1139.     ClientData srvToken;    /* Handle on server process passed to
  1140.                  * Rpc_Reply */
  1141.     int hostID;            /* Sprite ID of host invoking RPC */
  1142.     int command;        /* Command identifier */
  1143.     Rpc_Storage *storagePtr;    /* The request fields refer to the request
  1144.                  * buffers and also indicate the exact amount
  1145.                  * of data in the request buffers.  The reply
  1146.                  * fields are initialized to NIL for the
  1147.                  * pointers and 0 for the lengths.  This can
  1148.                  * be passed to Rpc_Reply */
  1149. {
  1150.     ReturnStatus status;
  1151.     Rpc_ReplyMem    *replyMemPtr;
  1152.     ProcMigCmd *commandPtr =
  1153.     (ProcMigCmd *) storagePtr->requestParamPtr;
  1154.     Proc_MigBuffer    inBuf;
  1155.     Proc_MigBuffer    outBuf;
  1156.     Proc_ControlBlock *procPtr;
  1157.     int requestSize;
  1158.  
  1159.     if (proc_MigDebugLevel > 5) {
  1160.     printf("Proc_RpcMigCommand: called from host %d with command %d commandPtr %x.\n",
  1161.            hostID, command, (int) commandPtr);
  1162.     }
  1163.     if (storagePtr->requestParamSize != sizeof(ProcMigCmd)) {
  1164.     if (proc_MigDebugLevel > 0) {
  1165.         printf("Proc_RpcMigCommand: called from host %d with invalid input buffer size (%d instead of %d).\n",
  1166.            hostID, storagePtr->requestParamSize, sizeof(ProcMigCmd));
  1167.     }
  1168.     status = GEN_INVALID_ARG;
  1169.     goto done;
  1170.     }
  1171.     
  1172.     if (commandPtr->remotePid != (Proc_PID) NIL) {
  1173.     PROC_GET_VALID_PCB(commandPtr->remotePid, procPtr);
  1174.     if (procPtr == (Proc_ControlBlock *) NIL) {
  1175.         if (proc_MigDebugLevel > 3) {
  1176.         panic("Proc_RpcMigCommand: Invalid pid: %x.\n", commandPtr->remotePid);
  1177.         }
  1178.         if (proc_MigDebugLevel > 1) {
  1179.         printf("Proc_RpcMigCommand: Invalid pid: %x.\n",
  1180.                commandPtr->remotePid);
  1181.         }
  1182.         status = PROC_NO_PEER;
  1183.         goto done;
  1184.     }
  1185.     } else {
  1186.     procPtr = (Proc_ControlBlock *) NIL;
  1187.     }
  1188.  
  1189.     if (commandPtr->command >= PROC_MIGRATE_CMD_NUM_TYPES ||
  1190.     commandPtr->command < 0) {
  1191.     if (proc_MigDebugLevel > 0) {
  1192.         printf("Proc_RpcMigCommand: invalid command number: %d.\n",
  1193.            commandPtr->command);
  1194.     }
  1195.     status = GEN_INVALID_ARG;
  1196.     goto done;
  1197.     }
  1198.     requestSize = storagePtr->requestDataSize;
  1199.     /*
  1200.      * Normally we just pass the buffer as it's given to us, but
  1201.      * it might be a piece of a larger buffer that we malloc and free.
  1202.      * In that case, do some sanity checking and then copy in the buffer.
  1203.      */
  1204.     if (commandPtr->totalSize == requestSize) {
  1205.     inBuf.size = requestSize;
  1206.     inBuf.ptr = storagePtr->requestDataPtr;
  1207.     } else {
  1208.     if (procPtr == (Proc_ControlBlock *) NIL) {
  1209.         if (proc_MigDebugLevel > 0) {
  1210.         printf("Proc_RpcMigCommand: partial buffer not allowed before process set up.\n");
  1211.         status = PROC_NO_PEER;
  1212.         goto done;
  1213.         }
  1214.     }
  1215.     if (commandPtr->offset == 0) {
  1216.         if (procPtr->migCmdBuffer != (Address) NIL) {
  1217.         if (proc_MigDebugLevel > 0) {
  1218.             printf("Proc_RpcMigCommand: buffer already established for process %x.\n",
  1219.                procPtr->processID);
  1220.         }
  1221.         free(procPtr->migCmdBuffer);
  1222.         }
  1223.         procPtr->migCmdBuffer = malloc(commandPtr->totalSize);
  1224.         procPtr->migCmdBufSize = commandPtr->totalSize;
  1225.     } else {
  1226.         if (procPtr->migCmdBuffer == (Address) NIL) {
  1227.         if (proc_MigDebugLevel > 0) {
  1228.             printf("Proc_RpcMigCommand: no buffer established for process %x.\n",
  1229.                procPtr->processID);
  1230.         }
  1231.         status = GEN_INVALID_ARG;
  1232.         goto done;
  1233.         }
  1234.         if (commandPtr->totalSize != procPtr->migCmdBufSize ||
  1235.         commandPtr->offset + requestSize > commandPtr->totalSize) {
  1236.         if (proc_MigDebugLevel > 0) {
  1237.             printf("Proc_RpcMigCommand: mismatch in buffer size for process %x.\n",
  1238.                procPtr->processID);
  1239.         }
  1240.         status = GEN_INVALID_ARG;
  1241.         goto done;
  1242.         }
  1243.     }
  1244.     bcopy(storagePtr->requestDataPtr,
  1245.           procPtr->migCmdBuffer + commandPtr->offset,
  1246.           requestSize);
  1247.     if (commandPtr->offset + requestSize < commandPtr->totalSize) {
  1248.         status = SUCCESS;
  1249.         goto done;
  1250.     }
  1251.     inBuf.size = commandPtr->totalSize;
  1252.     inBuf.ptr = procPtr->migCmdBuffer;
  1253.     }
  1254.     
  1255.     outBuf.size = 0;
  1256.     outBuf.ptr = (Address) NIL;
  1257.  
  1258.     status = (*commandCallbacks[commandPtr->command])
  1259.     (commandPtr, procPtr, &inBuf, &outBuf);
  1260. #ifdef lint
  1261.     status = ProcMigAcceptMigration(commandPtr, procPtr, &inBuf, &outBuf);
  1262.     status = ProcMigReceiveProcess(commandPtr, procPtr, &inBuf, &outBuf);
  1263.     status = ProcMigUpdateState(commandPtr, procPtr, &inBuf, &outBuf);
  1264.     status = ProcMigEncapCallback(commandPtr, procPtr, &inBuf, &outBuf);
  1265.     status = ProcMigDestroyCmd(commandPtr, procPtr, &inBuf, &outBuf);
  1266. #endif /* lint */
  1267.     /*
  1268.      * Free the malloc'ed buffer if it exists.
  1269.      */
  1270.     if ((procPtr != (Proc_ControlBlock *) NIL) &&
  1271.     (procPtr->migCmdBuffer != (Address) NIL)) {
  1272.     free(procPtr->migCmdBuffer);
  1273.     procPtr->migCmdBuffer = (Address) NIL;
  1274.     }
  1275.     if (status == SUCCESS && outBuf.size > 0) {
  1276.     storagePtr->replyDataPtr = outBuf.ptr;
  1277.     storagePtr->replyDataSize = outBuf.size;
  1278.  
  1279.     replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  1280.     replyMemPtr->paramPtr = (Address) NIL;
  1281.     replyMemPtr->dataPtr = outBuf.ptr;
  1282.     if (proc_MigDebugLevel > 5) {
  1283.         printf("Proc_RpcMigCommand: returning status %x.\n", status);
  1284.     }
  1285.     Rpc_Reply(srvToken, SUCCESS, storagePtr, Rpc_FreeMem,
  1286.         (ClientData) replyMemPtr);
  1287.     } else {
  1288. done:
  1289.     if (proc_MigDebugLevel > 2) {
  1290.         printf("Proc_RpcMigCommand: returning status %x.\n", status);
  1291.     }
  1292.     Rpc_Reply(srvToken, status,
  1293.           storagePtr, (int(*)()) NIL, (ClientData) NIL);
  1294.     }
  1295.     return(SUCCESS);
  1296. }
  1297.  
  1298.  
  1299. /*
  1300.  *----------------------------------------------------------------------
  1301.  *
  1302.  * Proc_RpcRemoteCall --
  1303.  *
  1304.  *    Handle a system call for a migrated process.
  1305.  *
  1306.  *    Note: now that this has been moved into the proc module, it
  1307.  *    can be collapsed into the routine it calls....
  1308.  *
  1309.  * Results:
  1310.  *    A return status.
  1311.  *
  1312.  * Side effects:
  1313.  *    None.
  1314.  *
  1315.  *----------------------------------------------------------------------
  1316.  */
  1317. /*ARGSUSED*/
  1318. ReturnStatus
  1319. Proc_RpcRemoteCall(srvToken, clientID, command, storagePtr)
  1320.     ClientData srvToken;    /* Handle on server process passed to
  1321.                  * Rpc_Reply */
  1322.     int clientID;        /* Sprite ID of client host */
  1323.     int command;        /* Command identifier */
  1324.     Rpc_Storage *storagePtr;    /* The request fields refer to the request
  1325.                  * buffers and also indicate the exact amount
  1326.                  * of data in the request buffers.  The reply
  1327.                  * fields are initialized to NIL for the
  1328.                  * pointers and 0 for the lengths.  This can
  1329.                  * be passed to Rpc_Reply */
  1330. {
  1331.     Rpc_ReplyMem    *replyMemPtr;
  1332.     Address returnData = (Address) NIL;
  1333.     int returnDataLength = 0;
  1334.     ReturnStatus status;
  1335.  
  1336.     status = RpcRemoteCall((Proc_RemoteCall *)storagePtr->requestParamPtr,
  1337.          storagePtr->requestDataPtr, storagePtr->requestDataSize,
  1338.          &returnData, &returnDataLength);
  1339.  
  1340.     storagePtr->replyDataPtr = returnData;
  1341.     storagePtr->replyDataSize = returnDataLength;
  1342.  
  1343.     replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  1344.     replyMemPtr->paramPtr = (Address) NIL;
  1345.     replyMemPtr->dataPtr = returnData;
  1346.     Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
  1347.         (ClientData) replyMemPtr);
  1348.  
  1349.     return(status);
  1350. }
  1351.